#ifndef K_SERIALIZER_H
#define K_SERIALIZER_H
#pragma once

#include "KStorage.h"
#include "KType.h"

class KSerializer : KNoCopy {
public:
    explicit KSerializer(KStorage *storage)
        : m_ok(true), m_storage(KVerify(storage)) {}
public:
    template <class T>
    KSerializer &operator>>(T &rhs);
    template <class T>
    KSerializer &operator<<(const T &rhs);
    operator bool() const   { return m_ok; }
public:
    void clear()            { m_ok = true; }
    bool isEmpty() const    { return !m_storage->bytesAvailable(); }
private:
    bool        m_ok;
    KStorage *  m_storage;
};

template <class T>
inline KSerializer &KSerializer::operator>>(T &rhs)
{
    if (m_ok) {
        m_ok = read(m_storage, rhs);
    }
    return *this;
}

template <class T>
inline KSerializer &KSerializer::operator<<(const T &rhs)
{
    if (m_ok) {
        m_ok = write(m_storage, rhs);
    }
    return *this;
}

template <class T>
inline bool read(KStorage *storage, T &rhs, typename std::enable_if<std::is_pod<T>::value>::type * = nullptr)
{
    return storage->read(&rhs, sizeof rhs);
}

template <class T>
inline bool write(KStorage *storage, const T &rhs, typename std::enable_if<std::is_pod<T>::value>::type * = nullptr)
{
    return storage->write(&rhs, sizeof rhs);
}

#endif // K_SERIALIZER_H